{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "SB93Ge748VQs"
      },
      "source": [
        "##### Copyright 2019 The TensorFlow Authors."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "0sK8X2O9bTlz"
      },
      "outputs": [],
      "source": [
        "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "# you may not use this file except in compliance with the License.\n",
        "# You may obtain a copy of the License at\n",
        "#\n",
        "# https://www.apache.org/licenses/LICENSE-2.0\n",
        "#\n",
        "# Unless required by applicable law or agreed to in writing, software\n",
        "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
        "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
        "# See the License for the specific language governing permissions and\n",
        "# limitations under the License."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "HEYuO5NFwDK9"
      },
      "source": [
        "# 检查 TensorFlow 图\n",
        "\n",
        "<table class=\"tfo-notebook-buttons\" align=\"left\">\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://tensorflow.google.cn/tensorboard/graphs\"><img src=\"https://tensorflow.google.cn/images/tf_logo_32px.png\" />在 TensorFlow.google.cn 访问</a>\n",
        "  </td>\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://colab.research.google.com/github/tensorflow/docs-l10n/blob/master/site/zh-cn/tensorboard/graphs.ipynb\"><img src=\"https://tensorflow.google.cn/images/colab_logo_32px.png\" />在 Google Colab 运行</a>\n",
        "  </td>\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://github.com/tensorflow/docs-l10n/blob/master/site/zh-cn/tensorboard/graphs.ipynb\"><img src=\"https://tensorflow.google.cn/images/GitHub-Mark-32px.png\" />在 GitHub 查看源代码</a>\n",
        "  </td>\n",
        "  <td>\n",
        "    <a href=\"https://storage.googleapis.com/tensorflow_docs/docs-l10n/site/zh-cn/tensorboard/graphs.ipynb\"><img src=\"https://tensorflow.google.cn/images/download_logo_32px.png\" />下载此 notebook</a>\n",
        "  </td>\n",
        "</table>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "56V5oun18ZdZ"
      },
      "source": [
        "## 概述\n",
        "\n",
        "TensorBoard 的 **图仪表盘** 是检查 TensorFlow 模型的强大工具。您可以快速查看模型结构的预览图，并确保其符合您的预期想法。 您还可以查看操作级图以了解 TensorFlow 如何理解您的程序。检查操作级图可以使您深入了解如何更改模型。例如，如果训练进度比预期的慢，则可以重新设计模型。"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "TOSJ-4nteBYG"
      },
      "source": [
        "本教程简要概述了如何在 TensorBoard 的 图仪表板中生成图诊断数据并将其可视化。您将为 Fashion-MNIST 数据集定义和训练一个简单的 Keras 序列模型，并学习如何记录和检查模型图。您还将使用跟踪API为使用新的 `tf.function` 注释创建的函数生成图数据。"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "zNI1-dflrAo0"
      },
      "source": [
        "## 设置"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "metadata": {
        "id": "6B95Hb6YVgPZ"
      },
      "outputs": [],
      "source": [
        "# Load the TensorBoard notebook extension.\n",
        "%load_ext tensorboard"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 22,
      "metadata": {
        "id": "_wqSAZExy6xV"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "TensorFlow version:  2.0.0-dev20190304\n"
          ]
        }
      ],
      "source": [
        "from __future__ import absolute_import\n",
        "from __future__ import division\n",
        "from __future__ import print_function\n",
        "\n",
        "from datetime import datetime\n",
        "from packaging import version\n",
        "\n",
        "import tensorflow as tf\n",
        "from tensorflow import keras\n",
        "\n",
        "print(\"TensorFlow version: \", tf.__version__)\n",
        "assert version.parse(tf.__version__).release[0] >= 2, \\\n",
        "    \"This notebook requires TensorFlow 2.0 or above.\""
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "Ao7fJW1Pyiza"
      },
      "outputs": [],
      "source": [
        "# Clear any logs from previous runs\n",
        "!rm -rf ./logs/ "
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "e25E37vd1xEW"
      },
      "source": [
        "## 定义一个 Keras 模型\n",
        "\n",
        "在此示例中，分类器是一个简单的四层顺序模型。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "skqORzvE3Egy"
      },
      "outputs": [],
      "source": [
        "# Define the model.\n",
        "model = keras.models.Sequential([\n",
        "    keras.layers.Flatten(input_shape=(28, 28)),\n",
        "    keras.layers.Dense(32, activation='relu'),\n",
        "    keras.layers.Dropout(0.2),\n",
        "    keras.layers.Dense(10, activation='softmax')\n",
        "])\n",
        "\n",
        "model.compile(\n",
        "    optimizer='adam',\n",
        "    loss='sparse_categorical_crossentropy',\n",
        "    metrics=['accuracy'])"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "qbjuoz9E3VC_"
      },
      "source": [
        "下载并准备训练数据"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "6TDmc41z3g38"
      },
      "outputs": [],
      "source": [
        "(train_images, train_labels), _ = keras.datasets.fashion_mnist.load_data()\n",
        "train_images = train_images / 255.0"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "8DV0xibO3bRC"
      },
      "source": [
        "## 训练模型并记录数据\n",
        "\n",
        "训练之前，请定义 [Keras TensorBoard callback](https://tensorflow.google.cn/api_docs/python/tf/keras/callbacks/TensorBoard), 并指定日志目录。通过将此回调传递给 Model.fit(), 可以确保在 TensorBoard 中记录图形数据以进行可视化。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 26,
      "metadata": {
        "id": "TU_L_u9SqQdH"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Epoch 1/5\n",
            "60000/60000 [==============================] - 2s 37us/sample - loss: 0.7073 - accuracy: 0.7577\n",
            "Epoch 2/5\n",
            "60000/60000 [==============================] - 2s 37us/sample - loss: 0.4838 - accuracy: 0.8297\n",
            "Epoch 3/5\n",
            "60000/60000 [==============================] - 2s 38us/sample - loss: 0.4439 - accuracy: 0.8417\n",
            "Epoch 4/5\n",
            "60000/60000 [==============================] - 2s 38us/sample - loss: 0.4230 - accuracy: 0.8478\n",
            "Epoch 5/5\n",
            "60000/60000 [==============================] - 2s 38us/sample - loss: 0.4124 - accuracy: 0.8520\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "<tensorflow.python.keras.callbacks.History at 0x7f2e202490b8>"
            ]
          },
          "execution_count": 26,
          "metadata": {
            "tags": []
          },
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Define the Keras TensorBoard callback.\n",
        "logdir=\"logs/fit/\" + datetime.now().strftime(\"%Y%m%d-%H%M%S\")\n",
        "tensorboard_callback = keras.callbacks.TensorBoard(log_dir=logdir)\n",
        "\n",
        "# Train the model.\n",
        "model.fit(\n",
        "    train_images,\n",
        "    train_labels, \n",
        "    batch_size=64,\n",
        "    epochs=5, \n",
        "    callbacks=[tensorboard_callback])"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "IRX5OIsi4TTV"
      },
      "source": [
        "## op-level graph\n",
        "\n",
        "启动 TensorBoard，然后等待几秒钟以加载 UI。通过点击顶部的 “graph” 来选择图形仪表板。 "
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "PFgFjlPEqXb9"
      },
      "outputs": [],
      "source": [
        "%tensorboard --logdir logs"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "EGlOqRp54ufD"
      },
      "source": [
        "默认情况下，TensorBoard 显示 **op-level图**。（在左侧，您可以看到已选择 “Default” 标签。）请注意，图是倒置的。 数据从下到上流动，因此与代码相比是上下颠倒的。 但是，您可以看到该图与 Keras 模型定义紧密匹配，并具有其他计算节点的额外边缘。\n",
        "\n",
        "图通常很大，因此您可以操纵图的可视化效果：\n",
        "\n",
        "* 滚动到 **zoom** 来放大和缩小\n",
        "* 拖到 **pan** 平移\n",
        "* 双击切换 **node expansion** 来进行节点扩展（一个节点可以是其他节点的容器）\n",
        "\n",
        "您还可以通过单击节点来查看元数据。这使您可以查看输入，输出，形状和其他详细信息。\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "F-2yw5qd7OpK"
      },
      "source": [
        "<img class=\"tfo-display-only-on-site\" src=\"https://github.com/tensorflow/tensorboard/blob/master/docs/images/graphs_computation.png?raw=1\"/>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "jDRynpVw53SJ"
      },
      "source": [
        "<img class=\"tfo-display-only-on-site\" src=\"https://github.com/tensorflow/tensorboard/blob/master/docs/images/graphs_computation_detail.png?raw=1\"/>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Oj9FSPdz6SO2"
      },
      "source": [
        "## 概念图\n",
        "\n",
        "除了执行图，TensorBoard 还显示一个“概念图”。 这只是 Keras 模型的视图。 如果您要重新使用保存的模型并且想要检查或验证其结构，这可能会很有用。\n",
        "\n",
        "要查看概念图，请选择 “keras” 标签。 在此示例中，您将看到一个折叠的 **Sequential** 节点。 双击节点以查看模型的结构："
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Qw9rbEcE6eZB"
      },
      "source": [
        "<img class=\"tfo-display-only-on-site\" src=\"https://github.com/tensorflow/tensorboard/blob/master/docs/images/graphs_tag_selection.png?raw=1\"/> <br/>\n",
        "<img class=\"tfo-display-only-on-site\" src=\"https://github.com/tensorflow/tensorboard/blob/master/docs/images/graphs_conceptual.png?raw=1\"/>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "zVuaKBifu-qF"
      },
      "source": [
        "## tf.functions 的图\n",
        "\n",
        "到目前为止的示例已经描述了 Keras 模型的图，其中这些图是通过定义 Keras 层并调用 Model.fit() 创建的。\n",
        "\n",
        "您可能会遇到需要使用 `tf.function` 注释来[[autograph]](https://tensorflow.google.cn/guide/function)的情况，即将 Python 计算函数转换为高性能 TensorFlow 图。对于这些情况，您可以使用 TensorBoard 中的 **TensorFlow Summary Trace API** 记录签名函数以进行可视化。"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "JIuhJnQ8w-dT"
      },
      "source": [
        "要使用 Summary Trace API ，请执行以下操作:\n",
        "\n",
        "*   使用 `tf.function` 定义和注释功能\n",
        "*   在函数调用站点之前立即使用 `tf.summary.trace_on()`\n",
        "*   通过传递 `profiler=True` 将配置文件信息（内存，CPU时间）添加到图中\n",
        "*   使用摘要文件编写器，调用 `tf.summary.trace_export()` 保存日志数据\n",
        "\n",
        "然后，您可以使用 TensorBoard 查看函数的行为。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "woI67Stgv_uY"
      },
      "outputs": [],
      "source": [
        "# The function to be traced.\n",
        "@tf.function\n",
        "def my_func(x, y):\n",
        "  # A simple hand-rolled layer.\n",
        "  return tf.nn.relu(tf.matmul(x, y))\n",
        "\n",
        "# Set up logging.\n",
        "stamp = datetime.now().strftime(\"%Y%m%d-%H%M%S\")\n",
        "logdir = 'logs/func/%s' % stamp\n",
        "writer = tf.summary.create_file_writer(logdir)\n",
        "\n",
        "# Sample data for your function.\n",
        "x = tf.random.uniform((3, 3))\n",
        "y = tf.random.uniform((3, 3))\n",
        "\n",
        "# Bracket the function call with\n",
        "# tf.summary.trace_on() and tf.summary.trace_export().\n",
        "tf.summary.trace_on(graph=True, profiler=True)\n",
        "# Call only one tf.function when tracing.\n",
        "z = my_func(x, y)\n",
        "with writer.as_default():\n",
        "  tf.summary.trace_export(\n",
        "      name=\"my_func_trace\",\n",
        "      step=0,\n",
        "      profiler_outdir=logdir)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "zCArnWzP0VuZ"
      },
      "outputs": [],
      "source": [
        "%tensorboard --logdir logs/func"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "WDl1PBFQ64xi"
      },
      "source": [
        "<img class=\"tfo-display-only-on-site\" src=\"https://github.com/tensorflow/tensorboard/blob/master/docs/images/graphs_autograph.png?raw=1\"/>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "1pLRaf3q6Nku"
      },
      "source": [
        "现在，您可以看到 TensorBoard 所理解的函数结构。 单击 “Profile” 按钮以查看 CPU 和内存统计信息。"
      ]
    }
  ],
  "metadata": {
    "accelerator": "GPU",
    "colab": {
      "collapsed_sections": [
        "SB93Ge748VQs"
      ],
      "name": "graphs.ipynb",
      "toc_visible": true
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
